
#include <algorithm>
#include <condition_variable>  // std::condition_variable
#include <iostream>
#include <map>
#include <mutex>  // std::mutex, std::unique_lock
#include <queue>
#include <sstream>
#include <thread>  // std::thread
#include <tuple>
#include <vector>
using namespace std;

std::mutex mtx;
std::condition_variable produce;
std::queue<int> myQueue;
// shared value by producers and consumers

void consumer() {
  std::unique_lock<std::mutex> lck(mtx);
  cout << "consumer" << endl;

  while (true) {
    {
      // std::unique_lock<std::mutex> lck(mtx);

      std::this_thread::sleep_for(std::chrono::seconds(1));

      if (myQueue.size() == 0) {
        produce.wait(lck);
      }

      if (myQueue.size() != 0) {
        int data = myQueue.front();
        myQueue.pop();
        std::cout << data << std::endl;
        produce.notify_one();
      }
    }
  }
}
// producer 先得到mtx, 得到后推入数据 ， produce.notify_one()应该是释放锁   ，
// produce.wait(lck); 等待重新获得锁
void producer(int id) {
  std::unique_lock<std::mutex> lck(mtx);
  cout << "producer" << endl;
  while (true) {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    for (int i = 0; i < 10; i++) {
      {
        // std::unique_lock<std::mutex> lck(mtx);
        if (myQueue.size() != 0) {
          produce.wait(lck);
        }
        if (myQueue.size() == 0) {
          myQueue.push(i);
          produce.notify_one();
        }
      }
    }
  }
}

int main() {
  std::thread consumers, producers;
  // spawn 10 consumers and 10 producers:
  consumers = std::thread(consumer);
  producers = std::thread(producer, 1);

  // join them back:
  producers.join();
  consumers.join();

  return 0;
}